package com.acme;

import java.io.FileNotFoundException;
import java.io.IOException;

import com.acme.bankapp.domain.bank.Account;
import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.bank.CheckingAccount;
import com.acme.bankapp.domain.bank.Client;
import com.acme.bankapp.domain.bank.Gender;
import com.acme.bankapp.domain.bank.SavingsAccount;
import com.acme.bankapp.exceptions.ClientExistsException;
import com.acme.bankapp.exceptions.NotEnoughFundsException;
import com.acme.bankapp.exceptions.OverDraftLimitExceededException;
import com.acme.bankapp.service.bank.BankDataLoaderService;
import com.acme.bankapp.service.bank.BankReport;
import com.acme.bankapp.service.bank.BankService;
import com.acme.bankapp.service.bank.EmailNotificationListener;
import com.acme.bankapp.service.bank.ParseFeedFileException;
import com.acme.mock.BankClient;
import com.acme.mock.BankServer;

public class BankApplication {	
	static final String KEY_LOAD_FEED = "-loadfeed";
	static final String KEY_LOAD_BANK = "-loadbank";
	static final String KEY_SERVER = "-server";
	static final String KEY_CLIENT = "-client";
	static final String KEY_STATISTIC = "-statistic";
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		Bank bank = new Bank();
		
		parseArgs(args, bank);
	}
	
	private static void parseArgs(String[] args, Bank bank) {
		
		for (int i=0; i<args.length; i++) {
			switch (args[i]) {
			case KEY_LOAD_BANK:
				try {
					if (i < args.length - 1) {
						bank = BankService.readBank(args[++i]);
						bank.addListener(new EmailNotificationListener());
					}
				} catch (ClassNotFoundException | IOException e) {
					System.out.println("Error while reading bank: " + e.getMessage());
				}
				break;
			case KEY_LOAD_FEED:
				try {
					if (i < args.length - 1)
						BankDataLoaderService.parseFeedFile(bank, args[++i]);
				} catch (ParseFeedFileException e) {
					System.out.println("Error while parsing file: " + e.getMessage());
				} catch (ArrayIndexOutOfBoundsException e) {
					System.out.println("Error while adding clients to bank: " + e.getMessage());
				} catch (FileNotFoundException e) {
					System.out.println("Error while parsing file: " + e.getMessage());
				} catch (ClientExistsException e) {
					System.out.println("Error while adding client <" + e.getClientSalutation() + "> to bank: " + e.getMessage());
				}
				break;
			case KEY_SERVER:
				BankServer.startServer(bank);
				break;
			case KEY_CLIENT:
				BankClient.startClient();
			case KEY_STATISTIC:
				BankReport.printStatistic(bank);
			}
		}
	}

	static void testEquals() {
		Account ac1 = new SavingsAccount(30);
		Account ac2 = new SavingsAccount(30);
		Account ac3 = new CheckingAccount(40, 20);
		Account ac4 = new CheckingAccount(40, 10);
		
		if (ac1.equals(ac2))
			System.out.println(ac1.toString() + " equals " + ac2.toString());
		else
			System.out.println(ac1.toString() + " not equals " + ac2.toString());

		if (ac3.equals(ac4))
			System.out.println(ac3.toString() + " equals " + ac4.toString());
		else
			System.out.println(ac3.toString() + " not equals " + ac4.toString());
			
		Client cl1 = new Client("Victory", Gender.FEMALE, ac1);
		Client cl2 = new Client("Victory", Gender.FEMALE, ac2);
		Client cl3 = new Client("Victory", Gender.FEMALE, ac3);
		
		if (cl1.equals(cl2))
			System.out.println(cl1.toString() + " equals " + cl2.toString());
		else
			System.out.println(cl1.toString() + " not equals " + cl2.toString());

		if (cl1.equals(cl3))
			System.out.println(cl1.toString() + " equals " + cl3.toString());
		else
			System.out.println(cl1.toString() + " not equals " + cl3.toString());
	}
	
	static void fillClients(Bank bank) {
		try {
			addClientToBank(bank, new Client("Pete", Gender.MALE, new SavingsAccount(50)));
			addClientToBank(bank, new Client("Mary", Gender.FEMALE, new CheckingAccount(40, 10)));
			addClientToBank(bank, new Client("John", Gender.MALE, new SavingsAccount(60)));
			addClientToBank(bank, new Client("Katy", Gender.FEMALE, new CheckingAccount(70, 30)));
			addClientToBank(bank, new Client("Katy", Gender.FEMALE, new CheckingAccount(10, 20)));
			addClientToBank(bank, new Client("Sean", Gender.MALE, new SavingsAccount(30)));
			addClientToBank(bank, new Client("Odry", Gender.FEMALE, new CheckingAccount(80, 15)));
			addClientToBank(bank, new Client("Steven", Gender.MALE, new SavingsAccount(20)));
			addClientToBank(bank, new Client("Taylor", Gender.FEMALE, new CheckingAccount(5, 5)));
			addClientToBank(bank, new Client("Mike", Gender.MALE, new SavingsAccount(10)));
			addClientToBank(bank, new Client("Valery", Gender.FEMALE, new CheckingAccount(0, 20)));
			addClientToBank(bank, new Client("Jessica", Gender.FEMALE, new SavingsAccount(120)));
		} catch (ArrayIndexOutOfBoundsException ex) {
			System.out.println("Error occured while adding clients to bank: " + ex.getMessage());
		}
	}
	
	static void addClientToBank(Bank bank, Client client) {
		try {
			BankService.addClient(bank, client);
		}
		catch (ClientExistsException ex) {
			System.out.println("Error while adding client <" + ex.getClientSalutation() + "> to bank: " + ex.getMessage());
		}
	}
	
	static void modifyBank(Bank bank) {
		for (Client client : bank.getClients()) {
			for (Account account : client.getAccounts()) {
				try {
					account.withDraw(15);
				}
				catch (OverDraftLimitExceededException ex) {
					System.out.println("Error while withdrawing on checking account <" + ex.getAccount() + "> of client <" + client.getClientSalutation() + ">: " + 
										ex.getMessage() + ". Max value of withdraw is <" + ex.getMaxWithdraw() + ">");
				}
				catch (NotEnoughFundsException ex) {
					System.out.println("Error while withdrawing on saving account of client <" + client.getClientSalutation() + ">: " + ex.getMessage());	
				}
				
				try {
					account.deposit(10);
				} catch (IllegalArgumentException ex) {
					System.out.println("Error while depositing on account of client <" + client.getClientSalutation() + ">: " + ex.getMessage());						
				}
			}
		}
	}
	
	static void printBalance(Bank bank) {
		System.out.println("Bank clients info:");
		for (Client client : bank.getClients()) {
			System.out.print(client.toString());
		}
	}
}
